using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace MKDS_Course_Editor.GCN.THP
{
	public partial class THPPlayer : Form
	{
		THP.Thp p;
		string file;
		public THPPlayer(string file)
		{
			this.file = file;
			InitializeComponent();
			GlassLib.Dwm.Glass[this].Enabled = true;
			GlassLib.Dwm.ThrowExceptionTypes = GlassLib.DwmExceptionTypes.None;
			GlassLib.Dwm.Glass[this].DragExtendedArea = true;
		}
		//AForge.Video.FFMPEG.VideoFileReader r;
		//AForge.Video.FFMPEG.VideoFileSource so;
		THP.Thp.ThpVideoInfo v;
		private void THPPlayer_Load(object sender, EventArgs e)
		{
			p = THP.Read(file);
			//r = new AForge.Video.FFMPEG.VideoFileReader();
			//r.Open(file);
			//so = new AForge.Video.FFMPEG.VideoFileSource(file);
			v = (THP.Thp.ThpVideoInfo)p.Components.InfoObjects[0];
			this.Width = (int)v.width;//v.width;
			this.Height = (int)v.height;//v.height;
			//so.NewFrame += new AForge.Video.NewFrameEventHandler(so_NewFrame);
			//so.Start();
			//AForge.Video.FFMPEG.VideoFileSource v = new AForge.Video.FFMPEG.VideoFileSource(file);
			backgroundWorker1.RunWorkerAsync(p);
			//System.Threading.Thread.Sleep(4000);
			//ret:
			//if (q.Count != 10) { goto ret; }
			timer1.Interval = (int)(1000f / p.Header.fps + 0.5f);
			timer1.Start();
			/*AForge.Video.VFW.AVIWriter a = new AForge.Video.VFW.AVIWriter();
			THP.Thp.ThpVideoInfo v = (THP.Thp.ThpVideoInfo)p.Components.InfoObjects[0];
			a.Open(@"D:\tmp.avi", (int)v.width, (int)v.height);
			a.FrameRate = (int)p.Header.fps;
			for (int i = 0; i < p.Header.numFrames; i++)
			{
				a.AddFrame(THP.GetFrame(p, i));
			}
			a.Close();
			AForge.Video.VFW.AVIFileVideoSource av = new AForge.Video.VFW.AVIFileVideoSource(@"D:\tmp.avi");*/
			//AForge.Video.AsyncVideoSource a = new AForge.Video.AsyncVideoSource(v);
			//videoSourcePlayer1.VideoSource = a;

			//pictureBox1.Image = THP.GetFrame(p, frame);
		}

		void so_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
		{
			pictureBox1.Image = eventArgs.Frame;
		}

		private void pictureBox1_Click(object sender, EventArgs e)
		{

		}
		int frame = 0;
		private void toolStripButton1_Click(object sender, EventArgs e)
		{
			//videoSourcePlayer1.Start();
			/*if (frame < p.Header.numFrames)
			{
				pictureBox1.Image = THP.GetFrame(p, frame++);
			}
			else
			{
				frame = 0;
			}*/
			//videoSourcePlayer1.Start();
		}
		System.Collections.Queue q = new System.Collections.Queue();
		private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
		{
			int bufferframe = 0;
			Bitmap b;
			int i;
			//IntPtr g_hWaveOut;
			//WaveLib.WaveNative.waveOutOpen(out g_hWaveOut, 0, 
			while (true)
			{
				if (((BackgroundWorker)sender).CancellationPending)
				{
					break;
				}
				//for (int i = 0; i < 1; i++)
				//{
				System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
				st.Start();
				b = THP.GetFrame((THP.Thp)e.Argument, bufferframe);
				st.Stop();
				bufferframe++;
				if (((THP.Thp)e.Argument).Header.maxAudioSamples != 0)
				{
					short[] s = new short[1];
					THP.thpAudioDecode(ref s, ((THP.Thp)e.Argument).Frames[bufferframe].AudioFrames[0], true, ((THP.Thp.ThpAudioInfo)((THP.Thp)e.Argument).Components.InfoObjects[1]).numChannels == 2);

					//WaveLib.WaveOutPlayer o = new WaveLib.WaveOutPlayer(0, new WaveLib.WaveFormat((int)((THP.Thp.ThpAudioInfo)((THP.Thp)e.Argument).Components.InfoObjects[1]).frequency, 16, (int)((THP.Thp.ThpAudioInfo)((THP.Thp)e.Argument).Components.InfoObjects[1]).numChannels), s.Length, 1,new WaveLib.BufferFillEventHandler(buffer));
					//WaveLib.WaveOutBuffer b = new WaveLib.WaveOutBuffer(o, 1);
					/*WaveLib.WaveNative.WaveHdr h = new WaveLib.WaveNative.WaveHdr();
					IntPtr po = Marshal.AllocHGlobal(s.Length);
					Marshal.StructureToPtr(s, po, true);
					h.lpData = po;//(LPSTR) & g_frames[i].buffer[0];
					h.dwBufferLength = s.Length * 2 * 2;
					h.dwBytesRecorded = 0;
					h.dwUser = (IntPtr)0;
					h.dwFlags = 0;
					h.dwLoops = 0;
					h.lpNext = (IntPtr)null;
					h.reserved = 0;
					WaveLib.WaveNative.waveOutPrepareHeader(WaveLib.WaveNative g_hWaveOut,ref h, sizeof(WAVEHDR));*/
				}
				//}
				//for (int i = 0; i < 1; i++)
				//{
				((BackgroundWorker)sender).ReportProgress((int)st.ElapsedMilliseconds, b);
				//}
				/*for (int i = 0; i < ((THP.Thp)e.Argument).Header.numFrames-10; i++)
				{
					((BackgroundWorker)sender).ReportProgress(-1, THP.GetFrame((THP.Thp)e.Argument, bufferframe));
					bufferframe++;
				}*/
				if (bufferframe == ((THP.Thp)e.Argument).Header.numFrames)
				{
					break;//bufferframe = 0;
				}
			}
		}
		/*private void buffer(IntPtr data, int size)
		{
			int blockCount = 1;//_wave.BlockCount;
			byte[] b = new byte[size];

			if (_file != null && (_looped || _lastBlock < blockCount))
			{
				MemoryStream ms = new MemoryStream();

				if (_leftOverBuffer != null)
				{
					ms.Write(_leftOverBuffer, 0, _leftOverBuffer.Length);
				}

				while (ms.Position < size)
				{
					_lastBlock++;

					if (_lastBlock >= blockCount)
					{
						if (!_looped)
						{
							while (ms.Position < size)
							{
								ms.WriteByte(0);
							}
							break;
						}
						else
						{
							_lastBlock = 0;
							_state = new DviAdpcmDecoder.AdpcmState();
						}
					}

					_file.SoundBank.ExportWaveBlockAsPCM(_wave.Index, _lastBlock, ref _state, _file.Stream, ms);
				}

				int extraData = (int)(ms.Position - size);

				ms.Seek(0, SeekOrigin.Begin);
				ms.Read(b, 0, size);

				if (extraData > 0)
				{
					_leftOverBuffer = new byte[extraData];
					ms.Read(_leftOverBuffer, 0, extraData);
				}
				else
				{
					_leftOverBuffer = null;
				}
			}
			else
			{
				for (int i = 0; i < b.Length; i++)
				{
					b[i] = 0;
				}
			}
			System.Runtime.InteropServices.Marshal.Copy(b, 0, data, size);

		}*/
		private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			q.Enqueue((Bitmap)e.UserState);
			toolStripStatusLabel1.Text = e.ProgressPercentage.ToString();
		}
		//DateTime prev = DateTime.MinValue;
		int frameprev = 0;
		int fps = 0;
		System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
		private void timer1_Tick(object sender, EventArgs e)
		{
			if (!s.IsRunning)
			{
				s.Start();
			}

			if (q.Count > frame)
			{
				pictureBox1.Image = (Bitmap)q.ToArray()[frame];
				frame++;
				frameprev++;
				if (frame == p.Header.numFrames)
				{
					frame = 0;
				}
			}
			Text = String.Format("THP Player [Frame {0}/{1}] [FPS {2}/{3}]", frame, p.Header.numFrames, fps, (int)p.Header.fps);
			if (s.Elapsed.TotalSeconds >= 1)
			{
				fps = frameprev;
				frameprev = 0;
				s.Stop();
				s.Reset();
				s.Restart();
			}
		}

		private void THPPlayer_FormClosing(object sender, FormClosingEventArgs e)
		{
			timer1.Stop();
			backgroundWorker1.CancelAsync();
		}

		private void glassBar1_ItemClicked(GlassLib.GlassBarItem item)
		{
			switch (item.Tag as string)
			{

			}
		}

		private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			toolStripButton1.Enabled = true;
		}

		private void toolStripButton1_Click_1(object sender, EventArgs e)
		{
			AForge.Video.VFW.AVIWriter wr = new AForge.Video.VFW.AVIWriter();
			wr.Open(@"D:\tmp.avi", (int)v.width, (int)v.height);
			wr.FrameRate = (int)p.Header.fps;
			wr.Quality = 100;
			foreach (Bitmap b in q)
			{
				wr.AddFrame(b);
			}
			wr.Close();
		}
	}
}
